﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using Gif.Components;

namespace mo_phong_cac_thuat_toan_sap_xep
{
    public delegate void BatDau();
    public partial class frmMain : DevComponents.DotNetBar.Office2007Form
    {
        private PhanTu[] cacPhanTu;
        private int giaiThuat = -1;
        private int phuongPhap = -1;
        private int tocDoCode = 200;
        private int tocDoPhanTu = 0;
        private AnimatedGifEncoder age = new AnimatedGifEncoder();
        private ArrayList alImage = new ArrayList();

        public frmMain()
        {
            InitializeComponent();
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            butBatDau.Enabled = false;
            butDung.Enabled = false;
            butTiepTuc.Enabled = false;
            butKetThuc.Enabled = false;
            butGhiLai.Enabled = false;
        }

        #region "Chụp form"

        /*
         * Chức năng chụp form dùng để chụp form và trả lại đối tượng Image được chụp.
         * Hàm này dùng để chụp mỗi khi form thay đổi
         * VD1: hiển thị thông báo --> chụp lại form dùng để làm record.
         * VD2: hoán vị các phần tử --> chụp lại form dùng để làm record.
         */

        private Image ChupForm()
        {
            Rectangle rec = this.Bounds;
            Bitmap bit = new Bitmap(rec.Width, rec.Height);
            bit.SetResolution(400, 300);
            Graphics g = Graphics.FromImage(bit);
            g.CopyFromScreen(this.Location.X, this.Location.Y, 0, 0, rec.Size);
            return bit;
        }

        #endregion

        #region "các trạng thái của hệ thống"

        private void TrangThaiBanDau()
        {
            age = new AnimatedGifEncoder();
            giaiThuat = -1;
            phuongPhap = -1;
            butChonGiaiThuat.Text = "Chọn giải thuật";
            butChonPhuongPhap.Text = "Chọn phương pháp";
            butNhapTrucTiep.Enabled = true;
            butNhapTuFile.Enabled = true;
            butTaoNgauNhien.Enabled = true;
            butChonGiaiThuat.Enabled = false;
            butChonPhuongPhap.Enabled = false;
            butBatDau.Enabled = false;
            butDung.Enabled = false;
            butTiepTuc.Enabled = false;
            butKetThuc.Enabled = false;
            butGhiLai.Enabled = false;
            lblMuiTenLen1.Visible = false;
            lblMuiTenLen2.Visible = false;
            lblMuiTenLen3.Visible = false;
        }

        private void TrangThaiDemo()
        {
            butNhapTrucTiep.Enabled = false;
            butNhapTuFile.Enabled = false;
            butTaoNgauNhien.Enabled = false;
            butChonGiaiThuat.Enabled = false;
            butChonPhuongPhap.Enabled = false;
            butBatDau.Enabled = false;
            butDung.Enabled = true;
            butKetThuc.Enabled = true;
            butGhiLai.Enabled = false;
        }

        #endregion

        #region "Nhập - Xóa phần tử"

        private void XoaPhanTu()
        {
            if (this.cacPhanTu != null && this.cacPhanTu.Length > 0)
            {
                foreach (PhanTu pt in cacPhanTu)
                {
                    this.Controls.Remove(pt);
                }
                cacPhanTu = null;
            }
        }

        private void butNhapTrucTiep_Click(object sender, EventArgs e)
        {
            butChonGiaiThuat.Enabled = true;
        }

        private void butNhapTuFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            StreamReader sr = null;
            String str = null, strText = "";
            XoaPhanTu();
            ofd.Title = "Chọn file";
            ofd.Filter = "Text file (*.txt)|*.txt";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                sr = File.OpenText(ofd.FileName);
                while ((str = sr.ReadLine()) != null)
                    strText += str + ";";
                sr.Close();
                strText = strText.Remove(strText.Length - 1);
                cacPhanTu = new PhanTu[strText.Split(';').Length];
                for (int i = 0; i < strText.Split(';').Length; i++)
                {
                    this.cacPhanTu[i] = new PhanTu();
                    this.cacPhanTu[i].Text = strText.Split(';')[i];
                    this.cacPhanTu[i].Location = new Point(10 + 58 * i, 530);
                    this.Controls.Add(this.cacPhanTu[i]);
                }
            }
            butChonGiaiThuat.Enabled = true;
        }

        private void butTaoNgauNhien_Click(object sender, EventArgs e)
        {
            Random r = new Random();
            int iSoPhanTu = r.Next(5, 21);
            iSoPhanTu = 6;
            XoaPhanTu();
            this.cacPhanTu = new PhanTu[iSoPhanTu];
            for (int i = 0; i < iSoPhanTu; i++)
            {
                this.cacPhanTu[i] = new PhanTu();
                this.cacPhanTu[i].Text = r.Next(100).ToString();
                this.cacPhanTu[i].Location = new Point(10 + 58 * i, 530);
                this.Controls.Add(this.cacPhanTu[i]);
            }
            butChonGiaiThuat.Enabled = true;
            ChupForm();
        }

        #endregion

        #region "Hiển thị code giải thuật"

        private void ThemCodeSelectionSortTang()
        {
            lstCode.Items.Clear();
            lstCode.Items.Add("void SelectionSort(int a[], int n)");
            lstCode.Items.Add("{");
            lstCode.Items.Add("    int min;");
            lstCode.Items.Add("    for(int i = 0; i < n -1; i++)");
            lstCode.Items.Add("    {");
            lstCode.Items.Add("        min = i;");
            lstCode.Items.Add("        for(int j = i + 1;j < n;j ++)");
            lstCode.Items.Add("            if(a[j] < a[min])");
            lstCode.Items.Add("                min = j;");
            lstCode.Items.Add("        HoanVi(a[min], a[i])");
            lstCode.Items.Add("    }");
            lstCode.Items.Add("}");
        }

        private void ThemCodeSelectionSortGiam()
        {
            lstCode.Items.Clear();
            lstCode.Items.Add("void SelectionSort(int a[], int n)");
            lstCode.Items.Add("{");
            lstCode.Items.Add("    int max;");
            lstCode.Items.Add("    for(int i = 0; i < n -1; i++)");
            lstCode.Items.Add("    {");
            lstCode.Items.Add("        max = i;");
            lstCode.Items.Add("        for(int j = i + 1;j < n;j ++)");
            lstCode.Items.Add("            if(a[j] > a[max])");
            lstCode.Items.Add("                max = j;");
            lstCode.Items.Add("        HoanVi(a[max], a[i])");
            lstCode.Items.Add("    }");
            lstCode.Items.Add("}");
        }

        private void ThemCodeInsertionSortTang()
        {
            lstCode.Items.Clear();
            lstCode.Items.Add("code ss tang");
        }

        private void ThemCodeInsertionSortGiam()
        {
            lstCode.Items.Clear();
            lstCode.Items.Add("code ss giam");
        }

        private void ThemCodeBubbleSortTang()
        {
            lstCode.Items.Clear();
            lstCode.Items.Add("for (int i = 0; i < n - 1; i++)");
            lstCode.Items.Add("    for (int j = n - 1; j > i; j--)");
            lstCode.Items.Add("        if (a[j] < a[j-1])");
            lstCode.Items.Add("            HoanVi(a[j-1], a[j]);");

        }

        private void ThemCodeBubbleSortGiam()
        {
            lstCode.Items.Clear();
            lstCode.Items.Add("for (int i = 0; i < n - 1; i++)");
            lstCode.Items.Add("    for (int j = n - 1; j > i; j--)");
            lstCode.Items.Add("        if (a[j] > a[j-1])");
            lstCode.Items.Add("            HoanVi(a[j-1], a[j];");
        }

        private void ThemCodeShakerSortTang()
        {
            lstCode.Items.Clear();
            lstCode.Items.Add("void ShakerSort(int a[], int n");
            lstCode.Items.Add("  {");
            lstCode.Items.Add("     int i;");
            lstCode.Items.Add("     int left, right, k;");
            lstCode.Items.Add("     left = 0; right = n-1; k = n-1;");
            lstCode.Items.Add("         while(left < right)");
            lstCode.Items.Add("             {");
            lstCode.Items.Add("               for(i = right; i > left; i--)");
            lstCode.Items.Add("                   if(a[i] < a[i-1])");
            lstCode.Items.Add("                     {");
            lstCode.Items.Add("                        swap(a[i], a[i-1]);");
            lstCode.Items.Add("                        k = i;");
            lstCode.Items.Add("                     }");
            lstCode.Items.Add("                    left = k;");
            lstCode.Items.Add("               for(i = left; i < right; i++)");
            lstCode.Items.Add("                   if(a[i] > a[i+1])");
            lstCode.Items.Add("                     {");
            lstCode.Items.Add("                        swap(a[i], a[i+1]);");
            lstCode.Items.Add("                        k = i;");
            lstCode.Items.Add("                     }");
            lstCode.Items.Add("                   right = k;");
            lstCode.Items.Add("              }");
            lstCode.Items.Add("  }");
        }

        private void ThemCodeShakerSortGiam()
        {
            lstCode.Items.Clear();
            lstCode.Items.Add("void ShakerSort(int a[], int n");
            lstCode.Items.Add("  {");
            lstCode.Items.Add("     int i;");
            lstCode.Items.Add("     int left, right, k;");
            lstCode.Items.Add("     left = 0; right = n-1; k = n-1;");
            lstCode.Items.Add("         while(left < right)");
            lstCode.Items.Add("             {");
            lstCode.Items.Add("               for(i = right; i > left; i--)");
            lstCode.Items.Add("                   if(a[i] > a[i-1])");
            lstCode.Items.Add("                     {");
            lstCode.Items.Add("                        swap(a[i], a[i-1]);");
            lstCode.Items.Add("                        k = i;");
            lstCode.Items.Add("                     }");
            lstCode.Items.Add("                    left = k;");
            lstCode.Items.Add("               for(i = left; i < right; i++)");
            lstCode.Items.Add("                   if(a[i] < a[i+1])");
            lstCode.Items.Add("                     {");
            lstCode.Items.Add("                        swap(a[i], a[i+1]);");
            lstCode.Items.Add("                        k = i;");
            lstCode.Items.Add("                     }");
            lstCode.Items.Add("                   right = k;");
            lstCode.Items.Add("              }");
            lstCode.Items.Add("  }");
        }

        private void ThemCodeMergeSortTang()
        {
            lstCode.Items.Clear();
            lstCode.Items.Add("code ms tang");
        }

        private void ThemCodeMergeSortGiam()
        {
            lstCode.Items.Clear();
            lstCode.Items.Add("code ms giam");

        }

        private void HienThiCode()
        {
            if (giaiThuat == -1 || phuongPhap == -1)
                return;
            lstCode.Items.Clear();
            if (giaiThuat == 0)
            {
                if (phuongPhap == 0)
                    ThemCodeSelectionSortTang();
                else
                    ThemCodeSelectionSortGiam();
            }
            else if (giaiThuat == 1)
            {
                if (phuongPhap == 0)
                    ThemCodeInsertionSortTang();
                else
                    ThemCodeInsertionSortGiam();
            }
            else if (giaiThuat == 2)
            {
                if (phuongPhap == 0)
                    ThemCodeBubbleSortTang();
                else
                    ThemCodeBubbleSortGiam();
            }
            else if (giaiThuat == 3)
            {
                if (phuongPhap == 0)
                    ThemCodeShakerSortTang();
                else
                    ThemCodeShakerSortGiam();
            }
            else
            {
                if (phuongPhap == 0)
                    ThemCodeMergeSortTang();
                else
                    ThemCodeMergeSortGiam();
            }

            if (this.cacPhanTu != null)
            {
                butBatDau.Enabled = true;
                butGhiLai.Enabled = true;
            }
        }

        #endregion

        #region "Hiển thị thông báo"

        private void HienThiTieuDe()
        {
            if (giaiThuat == -1 || phuongPhap == -1) return;
            string str = "GIẢI THUẬT ";
            if (giaiThuat == 0)
                str += "SELECTION SORT";
            else if (giaiThuat == 1)
                str += "INSERTION SORT";
            else if (giaiThuat == 2)
                str += "BUBBLE SORT";
            else if (giaiThuat == 3)
                str += "SHAKER SORT";
            else
                str += "MERGE SORT";
            str += " - ";
            if (phuongPhap == 0)
                str += "SẮP XẾP TĂNG";
            else
                str += "SẮP XẾP GIẢM";
            lblTieuDe.Text = str;
        }

        private void HienThiThongBao(String str)
        {
            lblThongBao.Text = str;
        }

        #endregion

        #region "Button chọn giải thuật - phương pháp sắp xếp"

        private void butSelectionSort_Click(object sender, EventArgs e)
        {
            giaiThuat = 0;
            butChonGiaiThuat.Text = "Selection Sort";
            butChonPhuongPhap.Enabled = true;
            HienThiCode();
            HienThiTieuDe();
        }

        private void butInsertionSort_Click(object sender, EventArgs e)
        {
            giaiThuat = 1;
            butChonGiaiThuat.Text = "Insertion Sort";
            butChonPhuongPhap.Enabled = true;
            HienThiCode();
            HienThiTieuDe();
        }

        private void butBubbleSort_Click(object sender, EventArgs e)
        {
            giaiThuat = 2;
            butChonGiaiThuat.Text = "Bubble Sort";
            butChonPhuongPhap.Enabled = true;
            HienThiCode();
            HienThiTieuDe();
        }

        private void butShakerSort_Click(object sender, EventArgs e)
        {
            giaiThuat = 3;
            butChonGiaiThuat.Text = "Shaker Sort";
            butChonPhuongPhap.Enabled = true;
            HienThiCode();
            HienThiTieuDe();
        }

        private void butMergeSort_Click(object sender, EventArgs e)
        {
            giaiThuat = 4;
            butChonGiaiThuat.Text = "Merge Sort";
            butChonPhuongPhap.Enabled = true;
            HienThiCode();
            HienThiTieuDe();
        }

        private void butSapXepTang_Click(object sender, EventArgs e)
        {
            phuongPhap = 0;
            butChonPhuongPhap.Text = "Sắp xếp tăng";
            siTocDo.Enabled = true;
            HienThiCode();
            HienThiTieuDe();
        }

        private void butSapXepGiam_Click(object sender, EventArgs e)
        {
            phuongPhap = 1;
            butChonPhuongPhap.Text = "Sắp xếp giảm";
            siTocDo.Enabled = true;
            HienThiCode();
            HienThiTieuDe();
        }

        #endregion

        #region "Selection Sort - Hùng"

        private void HoanVi(ref PhanTu e1, ref PhanTu e2)
        {
            PhanTu e;
            lblThongBao.Text = "";
            lblMuiTenLen1.Visible = false;
            lblMuiTenLen2.Visible = false;
            lblMuiTenLen3.Visible = false;
            int iKhoangCach = e2.Location.X - e1.Location.X;
            if (!e2.Location.Equals(e1.Location))
            {
                for (int i = 0; i < 50; i++)
                {
                    e1.DiLen(this.tocDoPhanTu);
                    e2.DiXuong(this.tocDoPhanTu);
                }
                for (int i = 0; i < iKhoangCach; i++)
                {
                    e1.DiSangPhai(this.tocDoPhanTu);
                    e2.DiSangTrai(this.tocDoPhanTu);
                }
                for (int i = 0; i < 50; i++)
                {
                    e1.DiXuong(this.tocDoPhanTu);
                    e2.DiLen(this.tocDoPhanTu);
                }
                e = e1;
                e1 = e2;
                e2 = e;
            }
        }

        private void SS_SapXepTang()
        {
            int min;
            //tô đậm code
            lstCode.SelectedIndex = 2;
            Thread.Sleep(this.tocDoCode);
            alImage.Add(ChupForm());

            for (int i = 0; i < this.cacPhanTu.Length; i++)
            {
                //tô đậm code
                lstCode.SelectedIndex = 3;
                Thread.Sleep(this.tocDoCode);
                alImage.Add(ChupForm());
                //hiển thị mũi tên cho vị trí i
                lblMuiTenLen1.Location = new Point(this.cacPhanTu[i].Location.X, this.cacPhanTu[i].Location.Y + 50);
                lblMuiTenLen1.Text = "i = " + i.ToString();
                lblMuiTenLen1.Visible = true;
                alImage.Add(ChupForm());
                Application.DoEvents();
                //tô đậm code
                lstCode.SelectedIndex = 5;
                Thread.Sleep(this.tocDoCode);
                alImage.Add(ChupForm());
                min = i;

                for (int j = i + 1; j < this.cacPhanTu.Length; j++)
                {
                    //tô đậm code
                    lstCode.SelectedIndex = 6;
                    Thread.Sleep(this.tocDoCode);
                    alImage.Add(ChupForm());
                    //hiển thị mũi tên cho vị trí j
                    lblMuiTenLen2.Location = new Point(this.cacPhanTu[j].Location.X, this.cacPhanTu[j].Location.Y + 50);
                    lblMuiTenLen2.Text = "j = " + j.ToString();
                    lblMuiTenLen2.Visible = true;
                    alImage.Add(ChupForm());
                    Application.DoEvents();
                    //tô đậm code
                    lstCode.SelectedIndex = 7;
                    alImage.Add(ChupForm());
                    Thread.Sleep(this.tocDoCode);

                    lblThongBao.Text = "So sánh phần tử ở vị trí thứ " + j.ToString() + " và " + min.ToString();
                    alImage.Add(ChupForm());
                    if (Int32.Parse(this.cacPhanTu[j].Text) < Int32.Parse(this.cacPhanTu[min].Text))
                    {
                        min = j;
                        //tô đậm code
                        lstCode.SelectedIndex = 8;
                        Thread.Sleep(this.tocDoCode);
                        alImage.Add(ChupForm());
                        //hiển thị mũi tên min
                        lblMuiTenLen3.Location = new Point(this.cacPhanTu[j].Location.X, this.cacPhanTu[j].Location.Y + 50);
                        lblMuiTenLen3.Text = "min = " + j.ToString();
                        lblMuiTenLen3.Visible = true;
                        alImage.Add(ChupForm());
                        Application.DoEvents();
                    }
                }
                if (i != min)
                {
                    lstCode.SelectedIndex = 9;
                    alImage.Add(ChupForm());
                    HoanVi(ref this.cacPhanTu[i], ref this.cacPhanTu[min]);
                }
                this.cacPhanTu[i].Image = Properties.Resources.blue_button;
            }
            lstCode.SelectedIndex = lstCode.Items.Count - 1;
            this.cacPhanTu[this.cacPhanTu.Length-1].Image = Properties.Resources.blue_button;
        }

        private void SS_SapXepGiam()
        {
            int max;
            //tô đậm code
            lstCode.SelectedIndex = 2;
            Thread.Sleep(this.tocDoCode);

            for (int i = 0; i < this.cacPhanTu.Length; i++)
            {
                //tô đậm code
                lstCode.SelectedIndex = 3;
                Thread.Sleep(this.tocDoCode);
                //hiển thị mũi tên cho vị trí i
                lblMuiTenLen1.Location = new Point(this.cacPhanTu[i].Location.X, this.cacPhanTu[i].Location.Y + 50);
                lblMuiTenLen1.Text = "i = " + i.ToString();
                lblMuiTenLen1.Visible = true;
                Application.DoEvents();
                //tô đậm code
                lstCode.SelectedIndex = 5;
                Thread.Sleep(this.tocDoCode);
                max = i;

                for (int j = i + 1; j < this.cacPhanTu.Length; j++)
                {
                    //tô đậm code
                    lstCode.SelectedIndex = 6;
                    Thread.Sleep(this.tocDoCode);
                    //hiển thị mũi tên cho vị trí j
                    lblMuiTenLen2.Location = new Point(this.cacPhanTu[j].Location.X, this.cacPhanTu[j].Location.Y + 50);
                    lblMuiTenLen2.Text = "j = " + j.ToString();
                    lblMuiTenLen2.Visible = true;
                    Application.DoEvents();
                    //tô đậm code
                    lstCode.SelectedIndex = 7;
                    Thread.Sleep(this.tocDoCode);
                    if (Int32.Parse(this.cacPhanTu[j].Text) > Int32.Parse(this.cacPhanTu[max].Text))
                    {
                        max = j;
                        //tô đậm code
                        lstCode.SelectedIndex = 8;
                        Thread.Sleep(this.tocDoCode);
                        //hiển thị mũi tên min
                        lblMuiTenLen3.Location = new Point(this.cacPhanTu[j].Location.X, this.cacPhanTu[j].Location.Y + 50);
                        lblMuiTenLen3.Text = "max = " + j.ToString();
                        lblMuiTenLen3.Visible = true;
                        Application.DoEvents();
                    }
                }
                lstCode.SelectedIndex = 9;
                HoanVi(ref this.cacPhanTu[i], ref this.cacPhanTu[max]);
                this.cacPhanTu[i].Image = Properties.Resources.blue_button;
            }
            lstCode.SelectedIndex = lstCode.Items.Count - 1;
        }

        #endregion

        #region "Insertion Sort - Linh"
        private void InsertSortTangDan()
        {
            PhanTu Node_Temp;
            int pos, i, x;
            for (i = 0; i < this.cacPhanTu.Length; i++)
            {
                lstCode.SelectedIndex = 3;
                //hiển thị mũi tên cho vị trí i
                //Thread.Sleep(this.tocDoPhanTu);


                Node_Temp = this.cacPhanTu[i];
                lstCode.SelectedIndex = 5;
                pos = i - 1;
                lstCode.SelectedIndex = 6;
                x = Int32.Parse(this.cacPhanTu[i].Text);
                Node_Temp.DiLen(this.tocDoPhanTu, 50);

                lblMuiTenLen1.Visible = true;
                lblMuiTenLen1.Location = new Point(this.cacPhanTu[i].Location.X, this.cacPhanTu[i].Location.Y + 50);
                lblMuiTenLen1.Text = "i = " + (i + 1).ToString();
                Application.DoEvents();
                this.cacPhanTu[i].Image = Properties.Resources.blue_button;
                while (pos >= 0 && Int32.Parse(this.cacPhanTu[pos].Text) > x)
                {
                    lstCode.SelectedIndex = 7;

                    //Thread.Sleep(this.tocDoPhanTu);

                    lstCode.SelectedIndex = 9;
                    HoanVi(ref this.cacPhanTu[pos], ref this.cacPhanTu[pos + 1]);

                    lblMuiTenLen3.Visible = true;
                    lblMuiTenLen3.Location = new Point(this.cacPhanTu[pos].Location.X, this.cacPhanTu[pos].Location.Y + 50);
                    lblMuiTenLen3.Text = "pos = " + pos.ToString();
                    Application.DoEvents();
                    this.cacPhanTu[i].Image = Properties.Resources.blue_button;
                    lstCode.SelectedIndex = 10;
                    pos--;

                }

            }

        }

        private void InsertSortGiam()
        {
            PhanTu Node_Temp;
            int pos, i, x;
            for (i = 0; i < this.cacPhanTu.Length; i++)
            {
                Node_Temp = this.cacPhanTu[i];
                pos = i - 1;
                x = Int32.Parse(this.cacPhanTu[i].Text);
                Node_Temp.DiLen(this.tocDoPhanTu, 50);
                while (pos >= 0 && Int32.Parse(this.cacPhanTu[pos].Text) < x)
                {

                    HoanVi(ref this.cacPhanTu[pos], ref this.cacPhanTu[pos + 1]);
                    pos--;
                }
            }
        }
        #endregion

        #region "Bubble Sort - Hùng"

        private void BS_SapXepTang()
        {
            for (int i = 0; i < this.cacPhanTu.Length - 1; i++)
            {
                lstCode.SelectedIndex = 0;
                Thread.Sleep(this.tocDoCode);
                lblMuiTenLen1.Location = new Point(this.cacPhanTu[i].Location.X, this.cacPhanTu[i].Location.Y + 50);
                lblMuiTenLen1.Text = "i = " + i.ToString();
                lblMuiTenLen1.Visible = true;
                Application.DoEvents();

                for (int j = this.cacPhanTu.Length - 1; j > i; j--)
                {
                    lstCode.SelectedIndex = 1;
                    Thread.Sleep(this.tocDoCode);
                    lblMuiTenLen2.Location = new Point(this.cacPhanTu[j].Location.X, this.cacPhanTu[j].Location.Y + 50);
                    lblMuiTenLen2.Text = "j = " + j.ToString();
                    lblMuiTenLen1.Visible = true;
                    lblMuiTenLen2.Visible = true;
                    Application.DoEvents();

                    lstCode.SelectedIndex = 2;
                    Thread.Sleep(this.tocDoCode);
                    if (Int32.Parse(this.cacPhanTu[j].Text) < Int32.Parse(this.cacPhanTu[j - 1].Text))
                    {
                        lstCode.SelectedIndex = 3;
                        Thread.Sleep(this.tocDoCode);
                        HoanVi(ref this.cacPhanTu[j - 1], ref this.cacPhanTu[j]);
                    }
                }
                this.cacPhanTu[i].Image = Properties.Resources.blue_button;
            }

            this.cacPhanTu[this.cacPhanTu.Length - 1].Image = Properties.Resources.blue_button;
            lblMuiTenLen1.Visible = false;
            lblMuiTenLen2.Visible = false;
            lstCode.SelectedIndex = lstCode.Items.Count - 1;
        }

        private void BS_SapXepGiam()
        {
                        for (int i = 0; i < this.cacPhanTu.Length - 1; i++)
            {
                lstCode.SelectedIndex = 0;
                Thread.Sleep(this.tocDoCode);
                lblMuiTenLen1.Location = new Point(this.cacPhanTu[i].Location.X, this.cacPhanTu[i].Location.Y + 50);
                lblMuiTenLen1.Text = "i = " + i.ToString();
                lblMuiTenLen1.Visible = true;
                Application.DoEvents();

                for (int j = this.cacPhanTu.Length - 1; j > i; j--)
                {
                    lstCode.SelectedIndex = 1;
                    Thread.Sleep(this.tocDoCode);
                    lblMuiTenLen2.Location = new Point(this.cacPhanTu[j].Location.X, this.cacPhanTu[j].Location.Y + 50);
                    lblMuiTenLen2.Text = "j = " + j.ToString();
                    lblMuiTenLen1.Visible = true;
                    lblMuiTenLen2.Visible = true;
                    Application.DoEvents();

                    lstCode.SelectedIndex = 2;
                    Thread.Sleep(this.tocDoCode);
                    if (Int32.Parse(this.cacPhanTu[j].Text) > Int32.Parse(this.cacPhanTu[j - 1].Text))
                    {
                        lstCode.SelectedIndex = 3;
                        Thread.Sleep(this.tocDoCode);
                        HoanVi(ref this.cacPhanTu[j - 1], ref this.cacPhanTu[j]);
                    }
                }
                this.cacPhanTu[i].Image = Properties.Resources.blue_button;
            }

            this.cacPhanTu[this.cacPhanTu.Length - 1].Image = Properties.Resources.blue_button;
            lblMuiTenLen1.Visible = false;
            lblMuiTenLen2.Visible = false;
            lstCode.SelectedIndex = lstCode.Items.Count - 1;
        }

        #endregion

        #region "Shaker Sort - Tâm"
        private void Shaker_SapXepTang()
        {
            int i, k, left, right, N;
            N = this.cacPhanTu.Length;
            k = 0;
            left = 0;
            right = N - 1;

            while (left < right)
            {
                //lstCode.SelectedIndex = 0;
                Thread.Sleep(this.tocDoCode);
                lblMuiTenLen1.Location = new Point(this.cacPhanTu[right].Location.X, this.cacPhanTu[right].Location.Y + 50);
                lblMuiTenLen1.Text = "r = " + right.ToString();
                lblMuiTenLen1.Visible = true;
                Application.DoEvents();
                for (i = right; i > left; i--)
                {
                    lstCode.SelectedIndex = 7;
                    Thread.Sleep(this.tocDoCode);
                    lblMuiTenLen2.Location = new Point(this.cacPhanTu[i].Location.X, this.cacPhanTu[i].Location.Y + 50);
                    lblMuiTenLen2.Text = "i = " + i.ToString();
                    lblMuiTenLen1.Visible = true;
                    lblMuiTenLen2.Visible = true;

                    Application.DoEvents();
                    Thread.Sleep(this.tocDoCode);
                    if (Int32.Parse(this.cacPhanTu[i].Text) < Int32.Parse(this.cacPhanTu[i - 1].Text))
                    {
                        lstCode.SelectedIndex = 8;
                        Thread.Sleep(this.tocDoCode);
                        lstCode.SelectedIndex = 10;
                        Thread.Sleep(this.tocDoCode);
                        HoanVi(ref this.cacPhanTu[i - 1], ref this.cacPhanTu[i]);
                        Thread.Sleep(this.tocDoCode);
                        lstCode.SelectedIndex = 11;
                        Thread.Sleep(this.tocDoCode);
                        //this.cacPhanTu[i].Image = Properties.Resources.blue_button;
                        k = i; // Dung bien k danh dau de bo qua doan da co thu tu.
                    }
                }
                this.cacPhanTu[left].Image = Properties.Resources.blue_button;
                if (k != left + 1)
                {
                    for (int j = k - 1; j > left; j--)
                    {
                        this.cacPhanTu[j].Image = Properties.Resources.blue_button;
                    }
                }
                left = k;
                Thread.Sleep(this.tocDoCode);
                lblMuiTenLen1.Location = new Point(this.cacPhanTu[left].Location.X, this.cacPhanTu[left].Location.Y + 50);
                lblMuiTenLen1.Text = "l = " + left.ToString();
                lblMuiTenLen1.Visible = true;
                for (i = left; i < right; i++)
                {
                    lstCode.SelectedIndex = 14;
                    Thread.Sleep(this.tocDoCode);
                    lblMuiTenLen2.Location = new Point(this.cacPhanTu[i].Location.X, this.cacPhanTu[i].Location.Y + 50);
                    lblMuiTenLen2.Text = "i = " + i.ToString();
                    lblMuiTenLen1.Visible = true;
                    lblMuiTenLen2.Visible = true;
                    Application.DoEvents();
                    Thread.Sleep(this.tocDoCode);
                    if (Int32.Parse(this.cacPhanTu[i].Text) > Int32.Parse(this.cacPhanTu[i + 1].Text))
                    {
                        lstCode.SelectedIndex = 15;
                        Thread.Sleep(this.tocDoCode);
                        lstCode.SelectedIndex = 17;
                        Thread.Sleep(this.tocDoCode);
                        HoanVi(ref this.cacPhanTu[i], ref this.cacPhanTu[i + 1]);
                        Thread.Sleep(this.tocDoCode);
                        lstCode.SelectedIndex = 18;
                        Thread.Sleep(this.tocDoCode);
                        k = i;
                    }
                }
                this.cacPhanTu[right].Image = Properties.Resources.blue_button;
                if (k != right - 1)
                {
                    for (int j = k + 1; j < right; j++)
                    {
                        this.cacPhanTu[j].Image = Properties.Resources.blue_button;
                    }
                }
                right = k;
            }
            for (int h = 0; h < this.cacPhanTu.Length - 1; h++)
            {
                this.cacPhanTu[h].Image = Properties.Resources.blue_button;
            }
        }

        private void Shaker_SapXepGiam()
        {
            int i, k, left, right, N;
            N = this.cacPhanTu.Length;
            k = 0;
            left = 0;
            right = N - 1;

            while (left < right)
            {
                //lstCode.SelectedIndex = 0;
                Thread.Sleep(this.tocDoCode);
                lblMuiTenLen1.Location = new Point(this.cacPhanTu[right].Location.X, this.cacPhanTu[right].Location.Y + 50);
                lblMuiTenLen1.Text = "r = " + right.ToString();
                lblMuiTenLen1.Visible = true;
                Application.DoEvents();
                for (i = right; i > left; i--)
                {
                    lstCode.SelectedIndex = 7;
                    Thread.Sleep(this.tocDoCode);
                    lblMuiTenLen2.Location = new Point(this.cacPhanTu[i].Location.X, this.cacPhanTu[i].Location.Y + 50);
                    lblMuiTenLen2.Text = "i = " + i.ToString();
                    lblMuiTenLen1.Visible = true;
                    lblMuiTenLen2.Visible = true;

                    Application.DoEvents();
                    Thread.Sleep(this.tocDoCode);
                    if (Int32.Parse(this.cacPhanTu[i].Text) > Int32.Parse(this.cacPhanTu[i - 1].Text))
                    {
                        lstCode.SelectedIndex = 8;
                        Thread.Sleep(this.tocDoCode);
                        lstCode.SelectedIndex = 10;
                        Thread.Sleep(this.tocDoCode);
                        HoanVi(ref this.cacPhanTu[i - 1], ref this.cacPhanTu[i]);
                        Thread.Sleep(this.tocDoCode);
                        lstCode.SelectedIndex = 11;
                        Thread.Sleep(this.tocDoCode);
                        //this.cacPhanTu[i].Image = Properties.Resources.blue_button;
                        k = i; // Dung bien k danh dau de bo qua doan da co thu tu.
                    }
                }
                this.cacPhanTu[left].Image = Properties.Resources.blue_button;
                if (k != left + 1)
                {
                    for (int j = k - 1; j > left; j--)
                    {
                        this.cacPhanTu[j].Image = Properties.Resources.blue_button;
                    }
                }
                left = k;
                Thread.Sleep(this.tocDoCode);
                lblMuiTenLen1.Location = new Point(this.cacPhanTu[left].Location.X, this.cacPhanTu[left].Location.Y + 50);
                lblMuiTenLen1.Text = "l = " + left.ToString();
                lblMuiTenLen1.Visible = true;
                for (i = left; i < right; i++)
                {
                    lstCode.SelectedIndex = 14;
                    Thread.Sleep(this.tocDoCode);
                    lblMuiTenLen2.Location = new Point(this.cacPhanTu[i].Location.X, this.cacPhanTu[i].Location.Y + 50);
                    lblMuiTenLen2.Text = "i = " + i.ToString();
                    lblMuiTenLen1.Visible = true;
                    lblMuiTenLen2.Visible = true;
                    Application.DoEvents();
                    Thread.Sleep(this.tocDoCode);
                    if (Int32.Parse(this.cacPhanTu[i].Text) < Int32.Parse(this.cacPhanTu[i + 1].Text))
                    {
                        lstCode.SelectedIndex = 15;
                        Thread.Sleep(this.tocDoCode);
                        lstCode.SelectedIndex = 17;
                        Thread.Sleep(this.tocDoCode);
                        HoanVi(ref this.cacPhanTu[i], ref this.cacPhanTu[i + 1]);
                        Thread.Sleep(this.tocDoCode);
                        lstCode.SelectedIndex = 18;
                        Thread.Sleep(this.tocDoCode);
                        k = i;
                    }
                }
                this.cacPhanTu[right].Image = Properties.Resources.blue_button;
                if (k != right - 1)
                {
                    for (int j = k + 1; j < right; j++)
                    {
                        this.cacPhanTu[j].Image = Properties.Resources.blue_button;
                    }
                }
                right = k;
            }
            for (int h = 0; h < this.cacPhanTu.Length - 1; h++)
            {
                this.cacPhanTu[h].Image = Properties.Resources.blue_button;
            }
        }
        #endregion

        #region "Merge Sort - Linh"
        private PhanTu[] a, b, c;
        private void Tach_Mang()
        {
            int m, pos, x, y, pos1;
            m = this.cacPhanTu.Length / 2;
            a = new PhanTu[m];
            c = new PhanTu[this.cacPhanTu.Length - m];
            for (int i = 0; i < m; i++)
            {
                a[i] = cacPhanTu[i];
                this.a[i].Image = Properties.Resources.blue_button;
                this.cacPhanTu[i].DiLen(this.tocDoPhanTu, 100);

            }
            for (int i = m; i < this.cacPhanTu.Length; i++)
            {
                c[i - m] = this.cacPhanTu[i];
                this.c[i - m].Image = Properties.Resources.blue_button;

                this.cacPhanTu[i].DiXuong(this.tocDoPhanTu, 100);
                this.cacPhanTu[i].DiSangTrai(this.tocDoPhanTu, 13 + 56 * m);

            }
            for (int i = 0; i < a.Length; i++)
            {
                x = Int32.Parse(this.a[i].Text);
                pos = i - 1;
                while (pos >= 0 && Int32.Parse(this.a[pos].Text) > x)
                {
                    HoanVi(ref this.a[pos], ref this.a[pos + 1]);
                    pos--;
                }
            }
            for (int i = 0; i < c.Length; i++)
            {
                y = Int32.Parse(this.c[i].Text);
                pos1 = i - 1;
                while (pos1 >= 0 && Int32.Parse(this.c[pos1].Text) > y)
                {
                    HoanVi(ref this.c[pos1], ref this.c[pos1 + 1]);
                    pos1--;
                }
            }
        }
        private int k;
        private void MergeSort_Tang()
        {
            b = new PhanTu[this.cacPhanTu.Length];
            int i, j;
            i = 0; j = 0;
            k = 0;
            Tach_Mang();
            while (i < a.Length && j < c.Length)
            {
                if (Int32.Parse(a[i].Text) <= Int32.Parse(c[j].Text))
                {
                    b[k] = this.a[i];
                    b[k].DiXuong(this.tocDoPhanTu, 100);
                    b[k].SangPhaiDenViTriX(this.tocDoPhanTu, 10 + 58 * k, 530);
                    //b[k].DiXuong(this.tocDoPhanTu, 25);
                    i++;
                }
                else
                {
                    b[k] = this.c[j];
                    b[k].DiLen(this.tocDoPhanTu, 100);
                    b[k].SangPhaiDenViTriX(this.tocDoPhanTu, 10 + 58 * k, 530);
                    //b[k].DiLen(this.tocDoPhanTu, 25);
                    j++;
                }
                k++;
            }
            if (i < a.Length)
            {
                for (int p = i; p < a.Length; p++)
                {
                    b[k] = a[p];
                    b[k].DiXuong(this.tocDoPhanTu, 100);
                    b[k].SangPhaiDenViTriX(this.tocDoPhanTu, 10 + 58 * k, 530);
                    //b[k].DiXuong(this.tocDoPhanTu, 25);
                    k++;
                }
            }
            else
            {
                for (int p = j; p < c.Length; p++)
                {
                    b[k] = c[p];
                    b[k].DiLen(this.tocDoPhanTu, 100);
                    b[k].SangPhaiDenViTriX(this.tocDoPhanTu, 10 + 58 * k, 530);
                    //b[k].DiLen(this.tocDoPhanTu, 25);
                    k++;
                }
            }
            //for (int u = 0; u < k; u++)
            //{
            //    b[u].Location = new Point(10 + 58 * u, 530);
            //}
        }
        #endregion

        private void butBatDau_Click(object sender, EventArgs e)
        {
            TrangThaiDemo();

            if (giaiThuat == 0)
            {
                if (phuongPhap == 0)
                    SS_SapXepTang();
                else
                    SS_SapXepGiam();
            }
            else if (giaiThuat == 1)
            {
            }
            else if (giaiThuat == 2)
            {
                if (phuongPhap == 0)
                    BS_SapXepTang();
                else
                    BS_SapXepGiam();
            }
            else if (giaiThuat == 3)
            {
                if (phuongPhap == 0)
                    Shaker_SapXepTang();
                else
                    Shaker_SapXepGiam();
            }
            else
            {
                if (phuongPhap == 0)
                    MergeSort_Tang();
            }
        }

        private void butDung_Click(object sender, EventArgs e)
        {
        }

        private void butTiepTuc_Click(object sender, EventArgs e)
        {
            butDung.Enabled = true;
            butTiepTuc.Enabled = false;
        }

        private void butKetThuc_Click(object sender, EventArgs e)
        {
            TrangThaiBanDau();
        }

        private void butGhiLai_Click(object sender, EventArgs e)
        {
            TrangThaiDemo();
            alImage = new ArrayList();
            if (giaiThuat == 0)
            {
                if (phuongPhap == 0)
                    SS_SapXepTang();
                else
                    SS_SapXepGiam();
            }
            else if (giaiThuat == 1)
            {
            }
            else if (giaiThuat == 2)
            {
                if (phuongPhap == 0)
                    BS_SapXepTang();
                else
                    BS_SapXepGiam();
            }
            else if (giaiThuat == 3)
            {
            }
            else
            {
            }

            age.Start("C:\\test.gif");
            age.SetDelay(0);
            for (int i = 0; i < alImage.Count - 1; i++)
            {
                Application.DoEvents();
                age.AddFrame((Image)alImage[i]);
            }
            age.Finish();
            MessageBox.Show("Ghi lại thành công.");
        }

        private void frmMain_Paint(object sender, PaintEventArgs e)
        {
            
        }

    }
}
